package com.project.common.filter;

import com.alibaba.fastjson.JSON;
import com.framework.core.result.APIObjResponse;
import com.project.biz.RedisBiz;
import com.project.common.headers.Headers;
import com.project.common.utils.ThreadLocalBuilder;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;

import javax.servlet.*;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;

/**
* @Description:   登陆拦截验证（默认拦截所有,不需要拦截的需要在EXCLUDEDLOGIN_ARRAY中配置）
* @Author:         wangzhiqiang
* @CreateDate:     2019-03-19 15:31
* @Version:        1.0
*/
@Slf4j
public class LoginFilter implements Filter {

    /**
     * 用户缓存信息
     */
    private RedisBiz redisBiz;

    /**
     * 无需登录URL配置
     */
    private String[] EXCLUDEDLOGIN_ARRAY = {"/user/login", "/user/userLogin", "/user/userRegister", "/user/getRegisterKey",
            "/user/forgetPassword", "/uploadImg", "/uploadImgs","/uploadPortraitImg","/user/getValidateCode","/imgCode",
            "/user/setTusers","/user/getTusers","/user/delTusers","/wx/payNotify","/wx/recoveryPayNotify","/home/getHomeConf",
            "/home/getHomeConf","/category/getAllCategory","/category/getAllCategory","/product/getProduct","/product/getProductSpecAndSku",
            "/product/getProductEva","/product/getProductDetail","/recommendProduct/selectRecommendProduct","/recoveryType/getAllRecoveryType",
            "/recoveryType/getRecoveryTypeDetail","/searchRecords/getUserSearchRecords","/export/exportProductData","/export/exportUserData"};

    /**
     * 构造方法
     * @param redisBiz
     */
    public LoginFilter(RedisBiz redisBiz){
        this.redisBiz = redisBiz;
    }

    @Override
    public void init(FilterConfig filterConfig) throws ServletException {

    }

    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        HttpServletRequest request = (HttpServletRequest) servletRequest;
        HttpServletResponse response = (HttpServletResponse) servletResponse;
        String uri = request.getRequestURI();
        //登陆认证TOKEN
        String token = request.getHeader(Headers.TOKEN);
        //判断用户信息是否已放入了Redis缓存
        boolean existsKey = false;

        //只要传入token,不管当前方法是否被登录拦截都增加用户信息
        if (StringUtils.isNotEmpty(token)){
            existsKey = this.redisBiz.checkToken(token);
            if (existsKey){
                //重新设置当前用户信息的过期时间，只要连续操作就不会过期
                this.redisBiz.resetExpire(token);
                //Token不为空并且用户信息不为空就加入本地线程池
                ThreadLocalBuilder.setThreadArg(token);
            }
        }
       // existsKey = true;
        if ("OPTIONS".equals(request.getMethod()) || !this.needLogin(uri)) { //不需要过滤直接传给下一个过滤器
            filterChain.doFilter(servletRequest, servletResponse);
            ThreadLocalBuilder.delThreadArg();
        }else {
            if (existsKey == false){
                response.setCharacterEncoding("utf-8");
                response.setContentType("application/json");
                response.setStatus(200);
                APIObjResponse objResp = APIObjResponse.needlogin();
                String jsonObject = JSON.toJSONString(objResp);
                response.getWriter().write(jsonObject);
                response.getWriter().flush();
                response.getWriter().close();
                log.info("未登录或登录已过期!");
            }else {
                filterChain.doFilter(servletRequest, servletResponse);
            }
        }
    }

    @Override
    public void destroy() {

    }

    /**
     * 判断当前URI是否需要登录
     * @param uri
     * @return true需登陆,false无需登录
     */
    public boolean needLogin( String uri){
        //解决部署到tomcat后接口名有前缀,导致无需的登录URL也需要登录问题
        if (uri.startsWith("/elephant-family")){
            uri = uri.substring("/elephant-family".length());
        }

        //放开swagger相关文件
        if(uri.contains("swagger") || uri.contains("api-docs") || uri.contains("csrf")){
            return false;
        }

        String[] excludedUrl = this.EXCLUDEDLOGIN_ARRAY; //获取无需登录的URL
        if (null != excludedUrl && excludedUrl.length > 0){
            for (String u : excludedUrl){
                if (uri.equals(u)){
                    return false;//如果当前URL在无需登录的数组中，则无需登录
                }
            }
        }

        return true;
    }

    /**
     * 根据名字获取cookie
     * @param request
     * @param name cookie名字
     * @return
     */
    public static Cookie getCookieByName(HttpServletRequest request,String name){
        Map<String,Cookie> cookieMap = ReadCookieMap(request);
        if(cookieMap.containsKey(name)){
            Cookie cookie = cookieMap.get(name);
            return cookie;
        }else{
            return null;
        }
    }

    /**
     * 将cookie封装到Map里面
     * @param request
     * @return
     */
    private static Map<String, Cookie> ReadCookieMap(HttpServletRequest request){
        Map<String,Cookie> cookieMap = new HashMap<>();
        Cookie[] cookies = request.getCookies();
        if(null!=cookies){
            for(Cookie cookie : cookies){
                cookieMap.put(cookie.getName(), cookie);
            }
        }
        return cookieMap;
    }
}
